package com.study.config;

import com.study.bean.Car;
import com.study.bean.Color;
import com.study.dao.BookDAO;
import org.springframework.context.annotation.*;

import javax.management.ValueExp;

/**
 *
 * 自动装配；
 *          Spring 利用依赖注入（DI），完成对IOC容器中各个组件的依赖关系赋值；
 *
 *  1) @Autowired :自动注入
 *      1） 默认优先按照类型去容器中找对应的组件：applicationContext.getBean(BookDAO.class),找到就赋值
 *      2)  如果找到多个相同类型的组件，在将属性的名称作为 组件的 id 去容器中查找
 *                                      applicationContext.getBean("bookDAO")
 *      3)  @Qualifier("bookDAO") ：使用 @Qualifier 指定需要装配的组件id ，而不是使用属性名
 *      4)  自动装配默认一定要将属性赋值好，没有就会报错；
 *          可以使用@Autowirted(required=false) 设置（容器中没有 该bean 也不会报错）;
 *      5） @Primary :让spring 进行自动装配的时候，默认使用首选的 bean;
 *          也可以使用 @Qualifier 指定需要装配的 bean 的名字
 *          BookService{
 *             @Qualifier("bookDAO")
 *             @Autowirted
 *              BookDAO bookDAO
 *           }
 *  2) Spring  还支持使用 @Resource(JSR250) 和 @Inject(JSR330) [java 规范的注解]
 *     @Resource:
 *     可以和 @Autowired 一样实现自动装配功能，默认是按照组件名称进行装配
 *      没有能支持 @Primary 功能 没有支持@Autowired (required=false);
 *      @Inject
 *      需要导入javax.inject 包 ，和Autowired的功能一样 ，没有 required=false 的功能
 *  @Autowired:Spring 定义的  ；@Resource  @Inject 都是java 规范
 *
 *  AutowiredAnnotationBeanPostProcessor  ：解析完成自动装配功能（通过解析上面的注解）
 *
 *  3) @Autowired : 构造器，参数 ，方法 ，属性 ，都是从容器中获取参数组件的值
 *  1） 【标注在方法位置】：@Bean+方法参数:参数从容器中获取;默认不写@Autowired 效果是一样的；都能自动装配
 *  2） 【标在构造器位置】: 如果组件只有一个有参构造器，这个有参构造器 @Autowired 可以省略，参数位置的组件还是可以从容器中获取
 *  3）  【标注在参数位置】
 *
 *  4) 、自定义组件想要使用Spring 容器底层的一些组件 (ApplicationContext ,BeanFactory, xxx)
 *          自定义组件实现 xxxAware:在创建对象的时候，会调用接口规定的方法注入相关组件: Aware ；
 *          把 Spring 底层一些组件注入到自定义的Bean 中；
 *          xxxAware：功能使用 XXXProcessor
 *          ApplicationContextAware => ApplicationContextAwareProcessor
 *          指定ApplicationContextAwareProcessor下的postProcessBeforeInitialization()方法 =>invokeAwareInterfaces() 判断 bean 实现了哪些 Aware ,做相应操作(调用setApplicationContext 方法将ioc容器注入进来)
 * @author wuwenbo
 * @date 2020/4/6 - 22:46
 */
@ComponentScan({"com.study.dao","com.study.service","com.study.controller","com.study.bean"})
@Configuration
public class MainConfigOfAutowired {
//    @Primary//自动装配首选装配该bean
    @Bean
    public BookDAO bookDAO2(){
        BookDAO bookDAO = new BookDAO();
        bookDAO.setLabel("2");
        return bookDAO;
    }

    /**
     * @Bean 标注的方法创建对象的时候，方法参数的值从容器中获取
     * @param car
     * @return
     */
    @Bean
    public Color color(Car car){
        Color color = new Color();
        color.setCar(car);
        return color;
    }
}
